﻿using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Linq;
using QDT.Cache;
using QDT.Core;
using QDT.Core.Deals;
using QDT.Core.Members;
using QDT.Common;
using QDT.Services.DTO;

namespace QDT.Services.Members
{
    public partial class UserService : ServiceBase, IUserService
    {

        public User CreateUser(int groupid,string username, string password, string email, bool isEffect)
        {
            if (DbProvider.D<User>().Count(x => x.UserName == username) > 0) throw new UserCreateException(UserCreateException.DuplicateUserName);

            if (DbProvider.D<User>().Count(x => x.Email == email) > 0) throw new UserCreateException(UserCreateException.DuplicateEmail);

            if (string.IsNullOrWhiteSpace(password)) throw new ArgumentNullException("password","密码不能为空. ");

            var group=DbProvider.GetByID<UserGroup>(groupid) ?? DbProvider.GetByID<UserGroup>(3);

            var user = new User(group, username, email, password, isEffect);

            DbProvider.Add(user);
            
            DbProvider.SaveChanges();

            return user;
        }

        public User CreateUser(string username, string password, string email, bool isEffect)
        {
            return CreateUser(0, username, password, email, isEffect);
        }

        public User CreateUser(string username, string password, string mobile)
        {
            return CreateUser(username, password, mobile, 0);
        }

        public User CreateUser(string username, string password, string mobile, int pid)
        {
            if (DbProvider.D<User>().Count(x => x.UserName == username) > 0) throw new UserCreateException(UserCreateException.DuplicateUserName);
            if (DbProvider.D<User>().Any(x => x.Mobile == mobile && x.MobilePassed)) throw new UserCreateException(UserCreateException.DuplicateMobile);
            if (string.IsNullOrWhiteSpace(password)) throw new ArgumentNullException("password", "密码不能为空. ");

            var group = DbProvider.GetByID<UserGroup>(0) ?? DbProvider.GetByID<UserGroup>(3);
            var user = new User(group, username, "", password);
            user.BindMobile(mobile);
            user.RecommendID = pid;

            DbProvider.Add(user);
            DbProvider.SaveChanges();

            return user;
        }

        public User CreateOfflineUser(string username, string password, string idCard, string realName, string phone)
        {
            if (DbProvider.D<User>().Count(x => x.UserName == username) > 0) throw new UserCreateException(UserCreateException.DuplicateUserName);

            if (DbProvider.D<User>().Count(x => x.Email == username + "@qdt.cc") > 0) throw new UserCreateException(UserCreateException.DuplicateEmail);

            if (string.IsNullOrWhiteSpace(password)) throw new ArgumentNullException("password", "密码不能为空. ");

//            var group = DbProvider.GetByID<UserGroup>(6);
            var group = DbProvider.GetByID<UserGroup>(1);

            var user = new User(group, username, username + "@qdt.cc", password);

            user.BindIDCard(idCard, realName);
            user.BindMobile(phone);
            user.BindSafePassword("123456");

            DbProvider.Add(user);

            DbProvider.SaveChanges();

            return user;
        }

        /// <summary>
        /// 验证用户
        /// </summary>
        /// <param name="nameOrEmailOrMobile"></param>
        /// <param name="password"></param>
        /// <param name="user"></param>
        /// <returns></returns>
        public bool ValidateUser(string nameOrEmailOrMobile, string password,out User user)
        {
            Check.Argument.IsNotEmpty(nameOrEmailOrMobile,"nameOrEmailOrMobile");

            var member = DbProvider.D<User>().FirstOrDefault(x => x.UserName == nameOrEmailOrMobile || x.Email == nameOrEmailOrMobile || x.Mobile == nameOrEmailOrMobile);

            if ( member == null || member.Password!=password.Hash() || member.IsBorrower)
            {
                user = null;
                return false;
            }

            user = member;

            if (!member.IsEffect || member.IsDelete)
            {
                return false;
            }
            return true;
            
        }

        public void UpdateUser(User user)
        {
            Check.Argument.IsNotNull(user, "user");

            DbProvider.Update(user);
            DbProvider.SaveChanges();
        }

        public User GetUserByID(int id)
        {
            return DbProvider.GetByID<User>(id);
        }

        public User GetUserByName(string username)
        {
            var cache = QDTCache.GetCacheService();
            var user = cache.RetrieveObject(CacheKeys.USERBYNAME.FormatWith(username.Hash())) as User;
            if (user == null)
            {
                user = DbProvider.NoTrack<User>().FirstOrDefault(x => x.UserName == username);
                cache.AddObject(CacheKeys.USERBYNAME.FormatWith(username.Hash()), user, 3);
            }
            return user;
        }

        public User GetUserByMobile(string mobilenum)
        {
            return string.IsNullOrWhiteSpace(mobilenum) ? null : DbProvider.D<User>().FirstOrDefault(x => x.Mobile == mobilenum && x.MobilePassed);
        }

        public User GetUserByEmail(string email)
        {
            return DbProvider.D<User>().FirstOrDefault(x => x.Email == email && x.EmailPassed);
        }

        public User GetUserByAll(string nameOrEmailOrMobile)
        {
            return DbProvider.D<User>().FirstOrDefault(x => x.UserName == nameOrEmailOrMobile || x.Email == nameOrEmailOrMobile || x.Mobile == nameOrEmailOrMobile);
        }

        /// <summary>
        /// 删除用户资金日志
        /// </summary>
        /// <param name="logid">日志id数组</param>
        public void DeleteUserLog(int[] logid) {
            foreach (var i in logid) {
                var log = DbProvider.GetByID<UserTransLog>(i);
                if (log == null) continue;
                DbProvider.Delete(log);
            }
            DbProvider.SaveChanges();
        }

        public void SetAutoBid(int userId, int id, decimal loadMoney, decimal minLoadMoney, int dealDateUpperLimit, int moneyRateLowerLimit, decimal retainMoney, bool assign = true, bool isIntelligence = false)
        {
            if (id > 0)
            {
                UpdateAutoBid(id, loadMoney, minLoadMoney, dealDateUpperLimit, moneyRateLowerLimit, retainMoney);
                return;
            }
            var autoBid = new UserAutoBid(userId, loadMoney, dealDateUpperLimit, minLoadMoney, moneyRateLowerLimit, retainMoney)
            {
                NotAssignAbleOnly = assign,
                YesNoIntelligence = isIntelligence
            };
            DbProvider.Add(autoBid);
            DbProvider.SaveChanges();
        }

        public void TurnOffAutoBid(int userId)
        {
            DbProvider.Delete<UserAutoBid>(o=>o.UserId.Equals(userId));
            DbProvider.SaveChanges();
        }

        public UserAutoBid GetAutoBidByUserId(int userId)
        {
            return DbProvider.D<UserAutoBid>().FirstOrDefault(o => o.UserId.Equals(userId));
        }

        public void UpdateAutoBid(int id, decimal loadMoney, decimal minLoadMoney, int dealDateUpperLimit, int moneyRateLowerLimit, decimal retainMoney)
        {
            var data = DbProvider.GetByID<UserAutoBid>(id);
            data.LoadMoney = loadMoney;
            data.MinLoadMoney = minLoadMoney;
            data.DealDateUpperLimit = dealDateUpperLimit;
            data.MoneyRateLowerLimit = moneyRateLowerLimit;
            data.RetainMoney = retainMoney;
            DbProvider.Update(data);
            DbProvider.SaveChanges();
        }

        public ICollection<RecentInvest> GetRecentInvestMoney(int userid)
        {
            var cache = QDTCache.GetCacheService();
            var records = cache.RetrieveObject(CacheKeys.RecentInvestMoneyKey.FormatWith(userid.ToString("0").Hash())) as ICollection<RecentInvest>;
            if (records == null || records.Count == 0)
            {
                records = new Collection<RecentInvest>();

                var time = DateTime.Now.Date;
                var year = time.Year;
                var month = time.Month;
                var start = new DateTime(year, month, 1);

                var credit = DbProvider.D<Credit>().Where(x => x.UserID == userid && x.Money > 0);

                for (int i = 0; i < 6; i++)
                {
                    var end = start.AddMonths(1);
                    var invests = credit.Where(x => x.CreateTime >= start && x.CreateTime < end);
                    if (invests.Any())
                    {
                        records.Add(new RecentInvest()
                        {
                            Time = start,
                            Money = invests.Sum(x=>x.Money)
                        });
                    }
                    else
                    {
                        records.Add(new RecentInvest()
                        {
                            Time = start,
                            Money = 0
                        });
                    }
                    start = start.AddMonths(-1);
                }

                cache.AddObject(CacheKeys.RecentInvestMoneyKey.FormatWith(userid.ToString("0").Hash()), records, 600);

            }
            return records;
        }
    }
}
